package br.com.business;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import br.com.bean.EngineBean;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;

public class EngineBusiness {
	private static final int TIMEOUT = 5000;
	private static final int MAX_PROPERTIES = 5;
	
	public HashMap<String, List<String>> getObjectByUriAndProperty(String endpoint, String uri, String property) {
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ "SELECT DISTINCT ?label ?object (isLiteral(?object) AS ?isLiteral) WHERE "
				+ "{ "
				+ "  <" + property + "> rdfs:label ?label . "
				+ "  <" + uri + "> <" + property + "> ?object ."
				+ "  FILTER(LANG(?label) = \"en\") "
				+ "} "
				+ "LIMIT 1";
		
		HashMap<String,List<String>> hashMap = executeSelectQuery(endpoint, queryString);
		
		return hashMap;
	}
	
	public EngineBean<String> getObjectByUriAndProperty2(String endpoint, String uri, String property) {
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ "SELECT DISTINCT ?label (str(?object) AS ?obj) (str(isLiteral(?object)) AS ?isLiteral) WHERE "
				+ "{ "
				+ "  <" + property + "> rdfs:label ?label . "
				+ "  <" + uri + "> <" + property + "> ?object ."
				+ "  FILTER(LANG(?label) = \"en\") "
				+ "} "
				+ "LIMIT 1";
		
		EngineBean<String> bean = executeSelectQuery2(endpoint, queryString);
		
		return bean;
	}
	
	public HashMap<String, List<String>> getPropertiesByUri(String endpoint, String uri) {
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ "SELECT DISTINCT ?predicate WHERE "
				+ "{ "
				+ "  ?predicate rdfs:label ?label ."
				+ "	  <" + uri + "> ?predicate [] ."
				+ "	  FILTER(LANG(?label) = \"en\")"
				+ "} "
				+ "LIMIT " + MAX_PROPERTIES;
		
		HashMap<String,List<String>> hashMap = executeSelectQuery(endpoint, queryString);
		
		return hashMap;
	}
	
	public String getUriByLabel(String endpoint, String label) {		
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ " SELECT ?uri WHERE " 
				+ " {"
				+ "   ?uri rdfs:label ?label ."
				+ "   FILTER(?label = \"" + label + "\"@en) "
				+ "} "
				+ " LIMIT 1";
		
		System.out.println(queryString);
				
		HashMap<String,List<String>> hashMap = executeSelectQuery(endpoint, queryString);
		if (hashMap == null) return null;
		
		return hashMap.get("uri").get(0);
	}
	
	public EngineBean<String> getUriByLabel2(String endpoint, String label, String extend) {		
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ " SELECT ?uri WHERE " 
				+ " {"
				+ "   ?uri rdfs:label ?label .";
		
		if("on".equals(extend)) queryString += "   FILTER(REGEX(?label, \"" + label + "\", \"i\")) ";
		else queryString += "   FILTER(?label = \"" + label + "\"@en) ";
				
		queryString += "} LIMIT 1";
		
		System.out.println(queryString);
				
		EngineBean<String> bean = this.executeSelectQuery2(endpoint, queryString);
		
		return bean;
	}
	
	public HashMap<String,List<String>> executeSelectQuery(String endpoint, String queryString) {		
		Query query = QueryFactory.create(queryString);
		QueryExecution qexec = QueryExecutionFactory.sparqlService(endpoint, query);
		qexec.setTimeout(TIMEOUT);

		HashMap<String, List<String>> resultList = null;
		
		try {
			ResultSet results = qexec.execSelect();
			resultList = prepareResultSet(results);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			qexec.close();
		}
		
		return resultList;
	}
	
	private static final HashMap<String, List<String>> prepareResultSet(ResultSet resultSet) {
		if(resultSet == null) return null;
		
		List<String> keys = resultSet.getResultVars();
		HashMap<String, List<String>> hashMap = new HashMap<String, List<String>>();
		
		for(String key : keys) hashMap.put(key, new ArrayList<String>());
		
		while(resultSet.hasNext()) {
			QuerySolution qs = resultSet.next();
			for(String key : keys) {
				if(qs.contains(key)) {
					hashMap.get(key).add(qs.get(key).toString());
				}
			}
		}
		
		return hashMap;
	}
	
	public EngineBean<String> getPropertiesByUri2(String endpoint, String uri) {
		String queryString = 
				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "
				+ "SELECT DISTINCT ?predicate WHERE "
				+ "{ "
				+ "  ?predicate rdfs:label ?label ."
				+ "	  <" + uri + "> ?predicate [] ."
				+ "	  FILTER(LANG(?label) = \"en\")"
				+ "} "
				+ "LIMIT " + MAX_PROPERTIES;
		
		EngineBean<String> hashMap = executeSelectQuery2(endpoint, queryString);
		
		return hashMap;
	}
	
	public EngineBean<String> executeSelectQuery2(String endpoint, String queryString) {		
		Query query = QueryFactory.create(queryString);
		QueryExecution qexec = QueryExecutionFactory.sparqlService(endpoint, query);
		qexec.setTimeout(TIMEOUT);

		EngineBean<String> resultList = null;
		
		try {
			ResultSet results = qexec.execSelect();
			resultList = prepareResultSet2(results);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(qexec != null) qexec.close();
		}
		
		return resultList;
	}
	
	private static final EngineBean<String> prepareResultSet2(ResultSet resultSet) {
		if(resultSet == null) return null;
		
		final EngineBean<String> engineBean = new EngineBean<String>();
		final List<String> keys = resultSet.getResultVars();
		
		while(resultSet.hasNext()) {
			QuerySolution qs = resultSet.next();
			for(String key : keys) engineBean.put(key, qs.get(key).toString());
		}
		
		return engineBean;
	}
	
	public static String formatAsHTMLTable(HashMap<String, List<String>> hashMap) {
		if(hashMap == null || hashMap.isEmpty()) return null;
		
		String firstKey = null;
		String result = "<table border='1'><tr>";
		for(String key : hashMap.keySet()) {
			if(firstKey == null) firstKey = key;
			result += "<th>" + key + "</th>";
		}
		result += "</tr>";
		
		for(int i = 0; i < hashMap.get(firstKey).size(); i++) {
			System.out.println("Linha :" + i);
			
			result += "<tr>";
			for(String key : hashMap.keySet()) {
				result += "<td>" + hashMap.get(key).get(i) + "</td>";
			}
			result += "</tr>";
		}
		result += "</table>";
		
		return result;
	}
}
